home *** CD-ROM | disk | FTP | other *** search
/ Belgian Amiga Club - ADF Collection / BS1 part 34.zip / BS1 part 34 / FredFish PD 314.adf / Zc / zcsrc.lzh / top / inst.c < prev    next >
C/C++ Source or Header  |  1989-05-26  |  7KB  |  403 lines

  1. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Tony Andrews
  2.  *
  3.  * Permission is granted to anyone to use this software for any purpose
  4.  * on any computer system, and to redistribute it freely, with the
  5.  * following restrictions:
  6.  * 1) No charge may be made other than reasonable charges for reproduction.
  7.  * 2) Modified versions must be clearly marked as such.
  8.  * 3) The authors are not responsible for any harmful consequences
  9.  *    of using this software, even if they result from defects in it.
  10.  */
  11.  
  12. /*
  13.  * Changes for Amiga version by Jeff Lydiatt marked with Jal.
  14.  */
  15.  
  16. /*
  17.  * Routines dealing with the parsing and output of instructions.
  18.  */
  19.  
  20. #include "top.h"
  21.  
  22. static    void    getarg();
  23. static    int    isreg();
  24.  
  25. /*
  26.  * addinst(bp, op, args) - add an instruction to block 'bp'
  27.  */
  28. void
  29. addinst(bp, op, args)
  30. register BLOCK    *bp;
  31. char    *op, *args;
  32. {
  33.     register INST    *ni;
  34.     register int    i;
  35.     register char    *s;
  36.     char    *arg2 = "";
  37.  
  38.     if (*op == '\0')    /* no instruction there */
  39.         return;
  40.  
  41.     ni = (INST *) alloc(sizeof(INST));
  42.  
  43.     ni->flags = 0;
  44.     ni->opcode = -1;
  45.     ni->next = NULL;
  46.     ni->prev = NULL;
  47.     ni->live = 0;
  48.     ni->rref = ni->rset = 0;
  49.  
  50.     ni->src.areg = ni->dst.areg = 0;
  51.     ni->src.ireg = ni->dst.ireg = 0;
  52.     ni->src.disp = ni->dst.disp = 0;
  53.     ni->src.astr = ni->dst.astr = NULL;
  54.     ni->src.amode = ni->dst.amode = NONE;
  55.  
  56.     /*
  57.      * Link into the block appropriately
  58.      */
  59.     if (bp->first == NULL) {
  60.         bp->first = bp->last = ni;
  61.     } else {
  62.         bp->last->next = ni;
  63.         ni->prev = bp->last;
  64.  
  65.         bp->last = ni;
  66.     }
  67.  
  68.     for (s = op; *s ;s++) {
  69.         /*
  70.          * Pseudo-ops start with a period, so the length
  71.          * specifier can't be the first character.
  72.          */
  73.         if (*s == '.' && s != op) {    /* length specifier */
  74.             *s++ = '\0';
  75.             switch (*s) {
  76.             case 'b':
  77.             case 'B': /*Jal*/
  78.                 ni->flags |= LENB;
  79.                 break;
  80.             case 'w':
  81.             case 'W': /*Jal*/
  82.                 ni->flags |= LENW;
  83.                 break;
  84.             case 'l':
  85.             case 'L': /*Jal*/
  86.                 ni->flags |= LENL;
  87.                 break;
  88.             default:
  89.                 fprintf(stderr, "Bad length spec '%c'\n", *s);
  90.                 exit(1);
  91.             }
  92.         }
  93.     }
  94.  
  95.     for (i=0; opnames[i] ;i++) {
  96.         if (stricmp(op, opnames[i]) == 0) { /*Jal*/
  97.             ni->opcode = i;
  98.             break;
  99.         }
  100.     }
  101.  
  102.     if (ni->opcode < 0) {
  103.         fprintf(stderr, "Unknown op '%s'\n", op);
  104.         exit(1);
  105.     }
  106.  
  107.     for (s = args; *s ;s++) {
  108.         /*
  109.          * skip chars in parens, since an operand split can't
  110.          * occur within.
  111.          */
  112.         if (*s == '(') {
  113.             while (*s != ')')
  114.                 s++;
  115.         }
  116.         if (*s == ',') {
  117.             *s++ = '\0';
  118.             arg2 = s;
  119.             break;
  120.         }
  121.     }
  122.  
  123.     getarg(&ni->src, args);
  124.     getarg(&ni->dst, arg2);
  125. }
  126.  
  127. /*
  128.  * delinst(bp, ip) - delete instruction 'ip' in block 'bp'
  129.  */
  130. void
  131. delinst(bp, ip)
  132. BLOCK    *bp;
  133. INST    *ip;
  134. {
  135.     INST    *pi, *ni;    /* previous and next instructions */
  136.  
  137.     pi = ip->prev;
  138.     ni = ip->next;
  139.  
  140.     if (pi != NULL)
  141.         pi->next = ni;
  142.     else
  143.         bp->first = ni;
  144.  
  145.     if (ni != NULL)
  146.         ni->prev = pi;
  147.     else
  148.         bp->last = pi;
  149.  
  150.     /*
  151.      * Free space used by the instruction.
  152.      */
  153.     if (ip->src.astr != NULL)
  154.         free(ip->src.astr);
  155.     if (ip->dst.astr != NULL)
  156.         free(ip->dst.astr);
  157.     free(ip);
  158. }
  159.  
  160. static    void
  161. getarg(op, s)
  162. register struct    opnd    *op;
  163. register char    *s;
  164. {
  165.     extern    long    atol();
  166.     register int    reg;
  167.     register char    *p;
  168.  
  169.     if (*s == '\0') {
  170.         op->amode = NONE;
  171.         return;
  172.     }
  173.  
  174.     if (*s == '#') {                /* immediate data */
  175.         op->amode = IMM;
  176.         s += 1;
  177.         if (isdigit(s[0]) || s[0] == '-')
  178.             op->disp  = atol(s);
  179.         else {
  180.             op->amode |= SYMB;
  181.             op->astr = strsave(s);
  182.         }
  183.         return;
  184.     } else if ((reg = isreg(s)) >= 0) {        /* reg. direct */
  185.         op->amode = REG;
  186.         op->areg = reg;
  187.     } else if (s[0] == '(' || (s[0] == '-' && s[1] == '(')) {
  188.         op->amode = REGI;
  189.         if (s[0] == '-') {
  190.             op->amode |= DEC;
  191.             s++;
  192.         }
  193.         s++;        /* skip the left paren */
  194.         if ((op->areg = isreg(s)) < 0) {
  195.             fprintf(stderr, "bad reg. '%s'\n", s);
  196.             exit(1);
  197.         }
  198.         s += 3;        /* skip the register and right paren */
  199.  
  200.         if (s[0] == '+')
  201.             op->amode |= INC;
  202.     } else if (!isdigit(s[0]) && (s[0] != '-')) {
  203.         op->amode = ABS;
  204.         op->astr = strsave(s);
  205.     } else {
  206.         for (p=s; isdigit(*p) || *p == '-' ;p++)
  207.             ;
  208.         if (*p != '(') {
  209.             /*
  210.              * Must have been absolute, but with an
  211.              * address instead of a symbol.
  212.              */
  213.             op->amode = ABS;
  214.             op->astr = strsave(s);
  215.             return;
  216.         }
  217.         *p++ = '\0';
  218.         op->disp = atol(s);
  219.         s = p;
  220.         if (s[0] == 'p' && s[1] == 'c') {    /* PC relative */
  221.             if (s[2] == ')') {
  222.                 op->amode = PCD;
  223.                 return;
  224.             }
  225.             op->amode = PCDX;
  226.             op->ireg = isreg(s+3);
  227.             if (s[6] == 'l')
  228.                 op->amode |= XLONG;
  229.         } else if ((reg = isreg(s)) >= 0) {
  230.             op->areg = reg;
  231.             if (s[2] == ')') {
  232.                 op->amode = REGID;
  233.                 return;
  234.             }
  235.             op->amode = REGIDX;
  236.             op->ireg = isreg(s+3);
  237.             if (s[6] == 'l')
  238.                 op->amode |= XLONG;
  239.         } else {
  240.             fprintf(stderr, "bad reg. '%s' after disp\n", s);
  241.             exit(1);
  242.         }
  243.     }
  244. }
  245.  
  246. /*
  247.  * characters that can terminate a register name
  248.  */
  249. #define    isterm(c) ((c) == '\0' || (c) == ')' || (c) == ',' || (c) == '.')
  250.  
  251. static    int
  252. isreg(s)
  253. char    *s;
  254. {
  255.     if (s[0] == 'd' && isdigit(s[1]) && isterm(s[2]))
  256.         return D0 + (s[1] - '0');
  257.     if (s[0] == 'a' && isdigit(s[1]) && isterm(s[2]))
  258.         return A0 + (s[1] - '0');
  259.     if (s[0] == 's' && s[1] == 'p' && isterm(s[2]))
  260.         return SP;
  261.  
  262.     return -1;
  263. }
  264.  
  265.  
  266. /*
  267.  * Routines for printing out instructions
  268.  */
  269.  
  270. static    char    *rstr();
  271. static    void    putop();
  272.  
  273. void
  274. putinst(ip)
  275. register INST    *ip;
  276. {
  277.     char    c;
  278.  
  279.     fprintf(ofp, "\t%s", opnames[ip->opcode]);
  280.  
  281.     switch (ip->flags) {
  282.     case LENB:
  283.         c = 'b';
  284.         break;
  285.     case LENW:
  286.         c = 'w';
  287.         break;
  288.     case LENL:
  289.         c = 'l';
  290.         break;
  291.     default:
  292.         c = '\0';
  293.         break;
  294.     }
  295.     if (c)
  296.         fprintf(ofp, ".%c", c);
  297.  
  298.     if (ip->src.amode != NONE) {
  299.         fprintf(ofp, "\t");
  300.         putop(&ip->src);
  301.     }
  302.  
  303.     if (ip->dst.amode != NONE) {
  304.         fprintf(ofp, ",");
  305.         putop(&ip->dst);
  306.     }
  307. #ifdef    DEBUG
  308.     if (debug)
  309.         fprintf(ofp, "\t\t* ref(%04x), set(%04x), live(%04x)",
  310.             reg_ref(ip), reg_set(ip), ip->live);
  311. #endif
  312.     fprintf(ofp, "\n");
  313. }
  314.  
  315. static    void
  316. putop(op)
  317. register struct    opnd    *op;
  318. {
  319.     switch (op->amode & MMASK) {
  320.     case NONE:
  321.         break;
  322.     case REG:
  323.         fprintf(ofp, "%s", rstr(op->areg));
  324.         break;
  325.     case IMM:
  326.         if (op->amode & SYMB)
  327.             fprintf(ofp, "#%s", op->astr);
  328.         else
  329.             fprintf(ofp, "#%ld", op->disp);
  330.         break;
  331.     case ABS:
  332.         fprintf(ofp, "%s", op->astr);
  333.         break;
  334.     case REGI:
  335.         if (op->amode & DEC)
  336.             fprintf(ofp, "-");
  337.         fprintf(ofp, "(%s)", rstr(op->areg));
  338.         if (op->amode & INC)
  339.             fprintf(ofp, "+");
  340.         break;
  341.     case REGID:
  342.         fprintf(ofp, "%ld(%s)", op->disp, rstr(op->areg));
  343.         break;
  344.     case REGIDX:
  345.         fprintf(ofp, "%ld(%s,", op->disp, rstr(op->areg));
  346.         fprintf(ofp, "%s.%c)", rstr(op->ireg),
  347.             (op->amode & XLONG) ? 'l' : 'w');
  348.         break;
  349.     case PCD:
  350.         fprintf(ofp, "%ld(pc)", op->disp);
  351.         break;
  352.     case PCDX:
  353.         fprintf(ofp, "%ld(pc,%s.%c)", op->disp, rstr(op->ireg),
  354.             (op->amode & XLONG) ? 'l' : 'w');
  355.         break;
  356.     default:
  357.         fprintf(stderr, "bad addr. mode in putop: %d\n", op->amode);
  358.         exit(1);
  359.     }
  360. }
  361.  
  362. static    char *
  363. rstr(r)
  364. register char    r;
  365. {
  366.     static    char    buf[3];
  367.  
  368.     if (r == SP) {
  369.         buf[0] = 's';
  370.         buf[1] = 'p';
  371.     } else if (r >= A0 && r <= A6) {
  372.         buf[0] = 'a';
  373.         buf[1] = '0' + (r - A0);
  374.     } else {
  375.         buf[0] = 'd';
  376.         buf[1] = '0' + (r - D0);
  377.     }
  378.     buf[2] = '\0';
  379.  
  380.     return buf;
  381. }
  382.  
  383. /*
  384.  * opeq(op1, op2) - test equality of the two instruction operands
  385.  */
  386. bool
  387. opeq(op1, op2)
  388. struct    opnd    *op1, *op2;
  389. {
  390.     if (op1->amode != op2->amode || op1->areg != op2->areg ||
  391.         op1->ireg  != op2->ireg  || op1->disp != op2->disp)
  392.         return FALSE;
  393.  
  394.     if (op1->astr == NULL)
  395.         return (op2->astr == NULL);
  396.     else {
  397.         if (op2->astr == NULL)
  398.             return FALSE;
  399.  
  400.         return (strcmp(op1->astr, op2->astr) == 0);
  401.     }
  402. }
  403.